<template>
  <div class="search-autocomplete" :class="{ 'is-focused': isFocused }">
    <!-- 搜索输入框 -->
    <div class="search-input-container">
      <input
        ref="inputRef"
        v-model="inputValue"
        type="text"
        class="search-input"
        :placeholder="placeholder"
        @input="handleInput"
        @focus="handleFocus"
        @blur="handleBlur"
        @keydown="handleKeydown"
        @keyup.enter="handleEnter"
      />
      <div class="search-icon">
        <PhMagnifyingGlass :size="20" />
      </div>
      <div v-if="inputValue && showClearBtn" class="clear-btn" @click="clearInput">
        <PhX :size="16" />
      </div>
    </div>

    <!-- 自动补全下拉列表 -->
    <transition name="dropdown">
      <div
        v-if="showSuggestions && (loading || totalSuggestions > 0 || (inputValue && inputValue.length >= minLength))"
        class="suggestions-dropdown"
        @mousedown.prevent
      >
        <div class="suggestions-list">
          <!-- 标题建议 -->
          <template v-if="titleSuggestions.length > 0">
            <div class="suggestion-group">
              <div class="group-header">
                <span class="group-title">标题匹配</span>
                <span class="group-count">{{ titleSuggestions.length }}</span>
              </div>
              <template v-for="(suggestion, index) in titleSuggestions" :key="`title-${suggestion.articleId}-${index}`">
                <div
                  class="suggestion-item"
                  :class="{ 'is-active': activeIndex === index }"
                  :style="{ '--item-index': index }"
                  @click="selectSuggestion(suggestion)"
                  @mouseenter="activeIndex = index"
                >
                  <div class="suggestion-content">
                    <div class="suggestion-text" v-html="suggestion.highlightText"></div>
                    <div class="suggestion-meta">
                      <span class="score">{{ suggestion.score.toFixed(1) }}</span>
                    </div>
                  </div>
                </div>
              </template>
            </div>
          </template>

          <!-- 摘要建议 -->
          <template v-if="summarySuggestions.length > 0">
            <div class="suggestion-group">
              <div class="group-header">
                <span class="group-title">内容匹配</span>
                <span class="group-count">{{ summarySuggestions.length }}</span>
              </div>
              <template v-for="(suggestion, index) in summarySuggestions" :key="`summary-${suggestion.articleId}-${index}`">
                <div
                  class="suggestion-item"
                  :class="{ 'is-active': activeIndex === (titleSuggestions.length + index) }"
                  :style="{ '--item-index': titleSuggestions.length + index }"
                  @click="selectSuggestion(suggestion)"
                  @mouseenter="activeIndex = titleSuggestions.length + index"
                >
                  <div class="suggestion-content">
                    <div class="suggestion-text summary-text" v-html="suggestion.highlightText"></div>
                    <div class="suggestion-meta">
                      <span class="score">{{ suggestion.score.toFixed(1) }}</span>
                    </div>
                  </div>
                </div>
              </template>
            </div>
          </template>
        </div>

        <!-- 加载状态 -->
        <div v-if="loading" class="loading-state">
          <div class="loading-spinner"></div>
          <span>搜索中...</span>
        </div>

        <!-- 无结果状态 -->
        <div v-if="!loading && inputValue && inputValue.length >= minLength && totalSuggestions === 0" class="no-results">
          <span>暂无相关建议</span>
        </div>
      </div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue';
import { PhMagnifyingGlass, PhX } from '@phosphor-icons/vue';
import { getAutocomplete } from '@/api/article';
import type { AutocompleteSuggestion } from '@/api/article/types';
import { debounce } from 'lodash-es';

interface Props {
  modelValue: string;
  placeholder?: string;
  categoryName?: string;
  size?: number;
  showClearBtn?: boolean;
  minLength?: number;
  debounceDelay?: number;
}

interface Emits {
  (e: 'update:modelValue', value: string): void;
  (e: 'search', keyword: string): void;
  (e: 'select', suggestion: AutocompleteSuggestion): void;
  (e: 'focus'): void;
  (e: 'blur'): void;
}

const props = withDefaults(defineProps<Props>(), {
  placeholder: '请输入搜索关键词...',
  size: 8,
  showClearBtn: true,
  minLength: 2,
  debounceDelay: 300
});

const emit = defineEmits<Emits>();

// 响应式状态
const inputRef = ref<HTMLInputElement>();
const inputValue = ref(props.modelValue);
const suggestions = ref<AutocompleteSuggestion[]>([]);
const loading = ref(false);
const isFocused = ref(false);
const showSuggestions = ref(false);
const activeIndex = ref(-1);

// 监听外部值变化
watch(() => props.modelValue, (newVal) => {
  inputValue.value = newVal;
});

// 监听输入值变化
watch(inputValue, (newVal) => {
  emit('update:modelValue', newVal);
});

// 计算属性：分离不同类型的建议
const titleSuggestions = computed(() => {
  return suggestions.value.filter(item => item.type === 'title').slice(0, 4);
});

const summarySuggestions = computed(() => {
  return suggestions.value.filter(item => item.type === 'summary').slice(0, 3);
});

// 防抖搜索函数
const debouncedSearch = debounce(async (keyword: string) => {
  if (!keyword || keyword.length < props.minLength) {
    suggestions.value = [];
    showSuggestions.value = false;
    return;
  }

  try {
    loading.value = true;
    const response = await getAutocomplete({
      keyword,
      categoryName: props.categoryName,
      size: props.size,
      type: 'all'
    });

    suggestions.value = response.data.allSuggestions || [];
    showSuggestions.value = true;
    activeIndex.value = -1;
  } catch (error) {
    console.error('自动补全搜索失败:', error);
    suggestions.value = [];
    showSuggestions.value = false;
  } finally {
    loading.value = false;
  }
}, props.debounceDelay);

// 处理输入
const handleInput = () => {
  debouncedSearch(inputValue.value);
};

// 处理焦点
const handleFocus = () => {
  isFocused.value = true;
  emit('focus');
  if (inputValue.value && totalSuggestions.value > 0) {
    showSuggestions.value = true;
  }
};

// 处理失焦
const handleBlur = () => {
  isFocused.value = false;
  emit('blur');
  // 延迟隐藏下拉列表，以便处理点击事件
  setTimeout(() => {
    showSuggestions.value = false;
    activeIndex.value = -1;
  }, 200);
};

// 计算总的建议数量
const totalSuggestions = computed(() => {
  return titleSuggestions.value.length + summarySuggestions.value.length;
});

// 根据索引获取建议项
const getSuggestionByIndex = (index: number) => {
  if (index < titleSuggestions.value.length) {
    return titleSuggestions.value[index];
  } else {
    return summarySuggestions.value[index - titleSuggestions.value.length];
  }
};

// 处理键盘事件
const handleKeydown = (event: KeyboardEvent) => {
  if (!showSuggestions.value || totalSuggestions.value === 0) return;

  switch (event.key) {
  case 'ArrowDown':
    event.preventDefault();
    activeIndex.value = Math.min(activeIndex.value + 1, totalSuggestions.value - 1);
    break;
  case 'ArrowUp':
    event.preventDefault();
    activeIndex.value = Math.max(activeIndex.value - 1, -1);
    break;
  case 'Enter':
    event.preventDefault();
    if (activeIndex.value >= 0) {
      selectSuggestion(getSuggestionByIndex(activeIndex.value));
    }
    break;
  case 'Escape':
    showSuggestions.value = false;
    activeIndex.value = -1;
    inputRef.value?.blur();
    break;
  }
};

// 处理回车搜索
const handleEnter = () => {
  if (activeIndex.value === -1) {
    emit('search', inputValue.value);
    showSuggestions.value = false;
  }
};

// 选择建议
const selectSuggestion = (suggestion: AutocompleteSuggestion) => {
  inputValue.value = suggestion.text;
  showSuggestions.value = false;
  activeIndex.value = -1;
  emit('select', suggestion);
};

// 清空输入
const clearInput = () => {
  inputValue.value = '';
  suggestions.value = [];
  showSuggestions.value = false;
  activeIndex.value = -1;
  nextTick(() => {
    inputRef.value?.focus();
  });
};

// 聚焦输入框
const focus = () => {
  inputRef.value?.focus();
};

// 暴露方法
defineExpose({
  focus,
  clearInput
});
</script>

<style scoped lang="less">
.search-autocomplete {
  position: relative;
  width: 100%;

  .search-input-container {
    height: 57px !important;
    position: relative;
    display: flex;
    align-items: center;
    background: #fff;
    border: 2px solid #e2e8f0;
    border-radius: 12px;
    transition: all 0.3s ease;
    overflow: hidden;

    &:hover {
      border-color: #cbd5e1;
    }

    .search-input {
      flex: 1;
      padding: 12px 16px;
      border: none;
      outline: none;
      font-size: 16px;
      color: #1a202c;
      background: transparent;

      &::placeholder {
        color: #a0aec0;
      }
    }

    .search-icon {
      padding: 0 12px;
      color: #718096;
      display: flex;
      align-items: center;
    }

    .clear-btn {
      padding: 8px;
      color: #a0aec0;
      cursor: pointer;
      display: flex;
      align-items: center;
      transition: color 0.2s ease;

      &:hover {
        color: #718096;
      }
    }
  }

  &.is-focused .search-input-container {
    border-color: #3182ce;
    box-shadow: 0 0 0 3px rgba(49, 130, 206, 0.1);
  }

  .suggestions-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: rgba(255, 255, 255, 0.98);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(226, 232, 240, 0.6);
    border-radius: 8px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
    z-index: 999999;
    max-height: 320px;
    overflow-y: auto;
    overflow-x: hidden;
    margin-top: 4px;
    box-sizing: border-box;

    // 自定义滚动条
    &::-webkit-scrollbar {
      width: 4px;
    }

    &::-webkit-scrollbar-track {
      background: transparent;
    }

    &::-webkit-scrollbar-thumb {
      background: #cbd5e1;
      border-radius: 2px;

      &:hover {
        background: #94a3b8;
      }
    }

        .suggestions-list {
      padding: 4px 0;
    }

    .suggestion-group {
      &:not(:last-child) {
        border-bottom: 1px solid #f1f5f9;
        margin-bottom: 8px;
        padding-bottom: 8px;
      }

      .group-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 8px 16px 4px;
        transition: all 0.3s ease;

        .group-title {
          font-size: 12px;
          font-weight: 600;
          color: #64748b;
          text-transform: uppercase;
          letter-spacing: 0.5px;
          transition: color 0.3s ease;
        }

        .group-count {
          font-size: 11px;
          color: #94a3b8;
          background: #f1f5f9;
          padding: 2px 6px;
          border-radius: 4px;
          transition: all 0.3s ease;
        }

        &:hover {
          .group-title {
            color: #475569;
          }

          .group-count {
            background: #e2e8f0;
            color: #64748b;
          }
        }
      }
    }

    .suggestion-item {
      padding: 10px 16px;
      cursor: pointer;
      transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
      color: #334155;
      position: relative;
      border-left: 3px solid transparent;
      word-wrap: break-word;
      overflow-wrap: break-word;
      border-radius: 6px;
      margin: 1px 4px;
      animation: slideInSuggestion 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
      animation-delay: calc(var(--item-index, 0) * 0.05s);

      &::before {
        content: '';
        position: absolute;
        top: 0;
        left: -3px;
        right: 0;
        bottom: 0;
        background: rgba(248, 250, 252, 0.4);
        transition: all 0.3s ease;
        border-radius: 6px;
        opacity: 0;
        transform: translateX(-8px) scale(0.95);
      }



      &:hover {
        transform: translateX(3px);

        &::before {
          opacity: 1;
          transform: translateX(0) scale(1);
        }
      }

      &.is-active {
        background: rgba(239, 246, 255, 0.6);
        transform: translateX(6px);

        &::before {
          opacity: 1;
          transform: translateX(0) scale(1);
          background: rgba(59, 130, 246, 0.08);
        }
      }

      .suggestion-content {
        text-align: left;
        position: relative;
        z-index: 1;
        width: 100%;
        box-sizing: border-box;
        min-width: 0;

        .suggestion-text {
          font-size: 14px;
          line-height: 1.4;
          color: #1e293b;
          margin-bottom: 6px;
          transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
          word-wrap: break-word;
          overflow-wrap: break-word;
          max-width: 100%;

          &.summary-text {
            font-size: 13px;
            color: #475569;
            display: -webkit-box;
            -webkit-line-clamp: 2;
            -webkit-box-orient: vertical;
            overflow: hidden;
          }

          // 高亮样式
          :deep(em) {
            font-style: normal;
            color: #2563eb;
            font-weight: 600;
            transition: all 0.25s ease;
            position: relative;
          }
        }

        .suggestion-meta {
          display: flex;
          justify-content: flex-end;
          align-items: center;
          font-size: 11px;
          color: #64748b;
          transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);

          .score {
            font-weight: 600;
            color: #059669;
            transition: all 0.3s ease;
            background: #f0fdf4;
            padding: 2px 6px;
            border-radius: 4px;
          }
        }
      }

      &:hover {
        .suggestion-content {
          .suggestion-text {
            color: #0f172a;

            :deep(em) {
              color: #1d4ed8;
              font-weight: 700;
            }
          }

          .suggestion-meta {
            .score {
              background: #dcfce7;
              color: #047857;
              transform: scale(1.05);
            }
          }
        }
      }

      // 键盘激活状态的特殊动画
      &.is-active {
        .suggestion-content {
          .suggestion-text {
            color: #0f172a;

            :deep(em) {
              color: #1d4ed8;
              font-weight: 700;
            }
          }

          .suggestion-meta {
            .score {
              background: #dcfce7;
              color: #047857;
              transform: scale(1.08);
            }
          }
        }
      }
    }

    .loading-state {
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 16px;
      color: #64748b;

      .loading-spinner {
        width: 14px;
        height: 14px;
        border: 2px solid #e2e8f0;
        border-top-color: #3b82f6;
        border-radius: 50%;
        animation: spin 1s linear infinite;
        margin-right: 8px;
      }
    }

    .no-results {
      text-align: center;
      padding: 16px;
      color: #64748b;
      font-size: 13px;
    }
  }
}

// 下拉动画
.dropdown-enter-active {
  transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.dropdown-leave-active {
  transition: all 0.25s cubic-bezier(0.4, 0, 1, 1);
}

.dropdown-enter-from {
  opacity: 0;
  transform: translateY(-8px) scale(0.95);
}

.dropdown-leave-to {
  opacity: 0;
  transform: translateY(-4px) scale(0.98);
}

// 加载动画
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

// 建议项渐入动画
@keyframes slideInSuggestion {
  0% {
    opacity: 0;
    transform: translateX(-12px) translateY(4px);
  }
  100% {
    opacity: 1;
    transform: translateX(0) translateY(0);
  }
}

// 响应式设计
@media (max-width: 768px) {
  .search-autocomplete {
    .search-input-container {
      .search-input {
        padding: 10px 12px;
        font-size: 14px;
      }
    }

    .suggestions-dropdown {
      max-height: 300px;

      .suggestion-item {
        padding: 10px 12px;

        .suggestion-content {
          .suggestion-text {
            font-size: 13px;
          }
        }
      }
    }
  }
}
</style>
